import { LocalKeys } from '@/types/knife4j'
import { MenuProps } from '@/types/menu/index'
import { IDocumentProps } from '@/store/modules/document/types'
import { dealPaths, generateDocRoute, generateApiGroup } from '@/utils/knife4j'
import localOperates from '@/utils/localforage'
import axios from 'axios'
import { defineStore } from 'pinia'
import md5 from 'md5'
// import { generatorMenu } from '@/types/menu'
import useDashboardStore from '../dashboard'
import { IDocket, ISwaggerResource } from './types'

const useKnifeStore = defineStore('knife', {
  state: (): {
    resources: ISwaggerResource[]
    docket: IDocket
    documentResource: IDocumentProps[]
    resourceOption: ISwaggerResource | null
    resourceMenus: MenuProps[] | []
    documentOption: IDocumentProps | undefined
  } => {
    return {
      resources: [
        {
          name: '默认分组',
          url: ''
        }
      ],
      docket: {
        swagger: '2.0.0',
        info: {
          title: '',
          description: '',
          version: '',
          termsOfService: '',
          contact: {
            name: '',
            url: '',
            email: ''
          },
          license: '',
          licenseUrl: ''
        },
        host: '',
        basePath: '',
        tags: [],
        paths: {},
        definitions: {},
        components: {}
      },
      documentResource: [],
      resourceOption: null,
      resourceMenus: [],
      documentOption: undefined
    }
  },
  persist: true,
  getters: {
    checkVersion: (state) => {
      return (version: string) => state.resources[0]?.swaggerVersion?.includes(version) ?? false
    }
  },
  actions: {
    async initKnife4j(options: Record<string, any>) {
      localOperates.removeItem('knifeGlobalResourceCache')
      let resourceUrl = 'swagger-resources'
      if (options.springdoc) {
        // copy from https://gitee.com/xiaoym/knife4j/pulls/61/files
        const path = window.location.pathname
        const index = path.lastIndexOf('/')
        const basePath = path.length === index + 1 ? path : path.substring(0, index)
        // swagger请求api地址
        resourceUrl = `${basePath}v3/api-docs/swagger-config`
      }

      axios.get<ISwaggerResource[]>(`/knife/${resourceUrl}`).then(async (response) => {
        const resources = response.data.map((item) => {
          return { ...item, id: md5(item.name) }
        })
        const defaultGroup = this.resources[0]
        // 存当前选中的组
        this.resourceOption = defaultGroup

        this.initDocket2(resources[0]).then((paths) => {
          resources[0].paths = paths
          this.resources = resources

          // 存入indexDB
          localOperates.setItem('knifeGlobalResourceCache', resources).then(() => {
            this.getKnifeMenus()
          })
        })
      })
      // })
    },
    initDocket2(group: ISwaggerResource) {
      const dashboard = useDashboardStore()
      return new Promise<MenuProps[]>((resolve) => {
        axios.get<IDocket>(`/knife/${group.url}`).then((response) => {
          const isVersion3 = this.checkVersion('3')
          this.docket = response.data
          if (isVersion3) {
            const {
              components: { schemas }
            } = response.data
            this.docket.swagger = this.docket?.openapi
            this.docket.definitions = schemas
          }
          dashboard.initDashboard(this.$state)
          this.documentResource = dealPaths(response.data, group.name)

          // 储存该组详细信息
          const paths = generateApiGroup([...this.documentResource], group.name)
          resolve(paths)
        })
      })
    },
    async changeGroup(group: ISwaggerResource) {
      const resourceCache: ISwaggerResource[] = await localOperates.getItem(LocalKeys.apisCache)
      const groupCache = resourceCache.find((item) => {
        return item.id === group.id
      })
      const paths = groupCache?.paths ?? (await this.initDocket2(group))
      if (groupCache && !groupCache?.paths) {
        // 更新分组信息
        Object.assign(groupCache, { paths })
        localOperates.setItem(LocalKeys.apisCache, [...resourceCache])
      }
      this.resourceOption = group
      this.resourceMenus = paths
    },
    async initDocket(defaultGroup: ISwaggerResource) {
      const dashboard = useDashboardStore()
      await axios.get<IDocket>(`/knife/${defaultGroup.url}`).then((response) => {
        const isVersion3 = this.checkVersion('3')
        this.docket = response.data
        if (isVersion3) {
          const {
            components: { schemas }
          } = response.data
          this.docket.swagger = this.docket?.openapi
          this.docket.definitions = schemas
        }
        dashboard.initDashboard(this.$state)
        this.documentResource = dealPaths(response.data.paths, defaultGroup.name)

        const asyncRoutes = generateDocRoute(this.documentResource)
        useAppStore().updateRouter(asyncRoutes)
      })
    },
    async getKnifeMenus(id?: string) {
      const resourceGroup: ISwaggerResource[] = await localOperates.getItem('knifeGlobalResourceCache')

      if (resourceGroup) {
        const paths: MenuProps[] =
          resourceGroup.find((item) => {
            return item.id === id || this.resourceOption?.id
          })?.paths ?? []
        this.resourceMenus = paths
        return paths
      }
      return []
    },
    updateDocumentOption(props: IDocumentProps) {
      this.documentOption = { ...props }
    }
  }
})

export default useKnifeStore
